#include "./../../../include/online/CacheSystem/LRUCache.h"
#include "./../../../include/online/Tools/MyLogger.h"

#include <fstream>
#include <sstream>
#include <iostream>

// 构造函数，初始化缓存容量
LRUCache::LRUCache() : _capacity(1000), _isUpdate(false) {}

// 析构函数
LRUCache::~LRUCache() {}

// 添加元素到缓存
// 如果 key 已存在，则将其移动到链表头
// 如果 key 不存在，且缓存已满，则删除最久未使用的元素
void LRUCache::addElement(const string &key, const json &value)
{
    auto it = _hashMap.find(key);
    if (it != _hashMap.end())
    {
        // key 已存在，移动到链表头
        _resultList.splice(_resultList.begin(), _resultList, it->second);
    }
    else
    {
        // 如果缓存已满，删除链表尾部元素
        if (_resultList.size() == _capacity)
        {
            auto &deleteNode = _resultList.back();
            _hashMap.erase(deleteNode.first);
            _resultList.pop_back();
        }
        // 插入新元素到链表头
        _resultList.emplace_front(key, value);
        _hashMap[key] = _resultList.begin();
    }
}

// 从文件读取缓存数据
// 每行格式：key value（value 为 JSON 字符串）
void LRUCache::readFromFile(const string &filename)
{
    ifstream ifs(filename, std::ios::in);
    if (!ifs)
    {
        LogInfo("无法打开文件：" + filename);
        return;
    }

    string line, key, jsonStr;
    while (getline(ifs, line))
    {
        istringstream iss(line);
        if (!(iss >> key >> jsonStr))
        {
            continue; // 读取失败则跳过
        }
        try
        {
            json value = json::parse(jsonStr); // 解析 JSON
            addElement(key, value);
        }
        catch (const std::exception &e)
        {
            LogInfo("JSON 解析错误：" + string(e.what()));
        }
    }
}

// 插入待更新的键值对（未命中缓存时调用）
void LRUCache::put_insert(const string &key, const json &value)
{
    _pendingUpdateList.emplace_back(key, value);
}

// 将缓存数据写入文件（快照模式，覆盖写）
void LRUCache::writeToFile(const string &filename)
{
    ofstream ofs(filename, std::ios::out);
    if (!ofs)
    {
        LogInfo("无法打开文件：" + filename);
        return;
    }

    for (const auto &ele : _resultList)
    {
        ofs << ele.first << " " << ele.second.dump() << endl;
    }
}

// 追加单个键值对到文件（日志模式，追加写）
void LRUCache::writeToFile(const string &filename, const string &key, const json &value)
{
    ofstream ofs(filename, std::ios::app);
    if (!ofs)
    {
        LogInfo("无法打开文件：" + filename);
        return;
    }
    ofs << key << " " << value.dump() << endl;
}

// 更新缓存数据（实现同步）
void LRUCache::update(const LRUCache &rhs)
{
    _isUpdate = true;
    for (const auto &ele : rhs._pendingUpdateList)
    {
        addElement(ele.first, ele.second);
    }
    _pendingUpdateList.clear();
    _isUpdate = false;
}

// 查询缓存中的 JSON 数据
// 如果 key 存在，则返回 true 并赋值给 j，否则返回 false
bool LRUCache::getjson(const string &key, json &j)
{
    auto it = _hashMap.find(key);
    if (it != _hashMap.end())
    {
        j = it->second->second;
        return true;
    }
    return false;
}

// 获取待更新的键值对列表
list<pair<string, json>> &LRUCache::getPendingUpdateList()
{
    return _pendingUpdateList;
}

// 获取当前缓存存储的所有键值对（按 LRU 规则排序）
list<pair<string, json>> &LRUCache::getResultList()
{
    return _resultList;
}
